// ==UserScript==
// @name         eureka.3.0
// @namespace    http://tampermonkey.net/
// @version      3.3
// @updateURL    http://code.cnhnb.com/liuhua/libra/tree/master/src/main/resources/eureka.js
// @description  查找接口3
// @author       liuhua
// @include      http://10.10.3.62:1111/
// @include      http://10.10.3.63:1111/
// @match        http://*/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    let serverUrl = "http://10.20.210.91:16261";
    let timer = null;
    let times = 2;
    let sync = false;
    let inter = null;
    let dialogShow = false;
    let apiData;
    function postForm(url, params, successCallBack, failCallBack) {
        let httpRequest = new XMLHttpRequest();
        httpRequest.onreadystatechange = function () {
            if (httpRequest.readyState === XMLHttpRequest.DONE) {
                if (httpRequest.status === 200) {
                    try {
                        let baseResult = JSON.parse(httpRequest.responseText)
                        if(baseResult.code == 0){
                            successCallBack && successCallBack(baseResult.data)
                        }else{
                            failCallBack && failCallBack(baseResult.msg);
                        }
                    } catch (error) {
                        console.error(`数据处理异常：`, httpRequest.responseText);
                    }
                } else {
                    console.error(`请求失败, 检测请求地址是否有效【${url}】`);
                    failCallBack && failCallBack(httpRequest.responseText)
                }
            }
        };
        httpRequest.open('POST', url);
        httpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        httpRequest.send(params);
    }
    function initSearchUI() {
        let commonStyle = `.createCode{height:25px !important;background-color: #1c93e3 !important;}#minetitle div{height:30;line-height:30px}#minetitle div.xk{max-width:456px;}#minetitle{min-width:200px;z-index:1000001;position: absolute;color: #ffffff;font-size: 14px;padding: 4px 10px;background: rgba(40, 40, 40, 0.8);border: solid 1px #e9f7f6;border-radius:5px;}.extends{z-index: 100000;position:fixed;display:inline-block;right:-846px;top:82px;font-size:14px;background: #ffffff;border-left: 2px solid #dcdfe6;cursor:default;}.oper-kai{display: inline-block;padding: 5px;background-color: #f5f8fa;vertical-align: middle;position: relative;border: 1px solid #dcdfe6;border-left: none;height: 40px;line-height: 1;outline: 0;}.oper{display:inline-table;border: 0px solid #dfbbf0;}.oper-input{background-color:#fff;border:1px solid #dcdfe6;box-sizing:border-box;color:#606266;font-size:inherit;height:40px;line-height:40px;padding:0 15px;width:700px;cursor:default;outline:0;vertical-align:middle;display:inline-block}.oper-desc{position:absolute;right:150px;top:10px}.oper-button{background-color:#f5f8fa;color:#000;vertical-align:middle;display:inline-block;position:relative;border:1px solid #dcdfe6;border-left:none;height:40px;line-height:1;border-radius:0 4px 4px 0;padding:0 20px;width:120px;white-space:nowrap;outline:0}.list{cursor:default;margin-top:0px;background:#fff;box-shadow:3px 4px 5px 0 #999}.list.hidden{display:none}.list-ul{text-align: left;width:100%;margin:0;padding:0;list-style:none;width:820px;border:1px solid #dcdfe6;max-height:500px;overflow-y:auto}.list-zw{width:120px}.list-li{padding:10px 15px;border-bottom:1px solid #dcdfe6;overflow:hidden;box-sizing:border-box}.list-li.active{background:#f5f8fa}.list-li-left{width:60%;float:left;white-space:nowrap;word-break:break-all;overflow:hidden;text-overflow:ellipsis;box-sizing:border-box}.list-li-right{box-sizing:border-box;width:40%;float:right;padding-left:15px;white-space:nowrap;word-break:break-all;overflow:hidden;text-overflow:ellipsis;text-align:right}`;
        let styleTextNode = document.createTextNode(commonStyle);
        let styleElement = document.createElement('style');
        styleElement.appendChild(styleTextNode)
        document.body.appendChild(styleElement);
        let rootDiv = document.createElement('div');
        rootDiv.setAttribute("id", "swagger-ui-extends-root");
        document.body.appendChild(rootDiv);
        let rootHtml = `<div class="extends" id="dialog"><button class="oper-kai" id="showBtn">开</button><div class="oper"><input class="oper-input" id="operInput" type="text" maxlength="60" placeholder="路径或服务名:或服务名:路径(冒号不能丢，可使用空格、中文)，例如：supply:supply/info"/><span class="oper-desc" id="operDesc">共找到0个接口</span><button class="oper-button" id="operButton">清空</button></div><button class="oper-kai" id="hideBtn">隐</button><div class="list hidden" id="operList"><ul class="list-ul" id="operUl"></ul></div></div>`;
        rootDiv.innerHTML = rootHtml;
        document.getElementById("operInput").addEventListener("input", inputSearch);
        document.getElementById("operInput").addEventListener("focus", inputSearch);
        //document.getElementById("operInput").addEventListener("blur", listClean);
        document.getElementById("operButton").addEventListener("focus", inputClean);
        document.getElementById("showBtn").addEventListener("click", show);
        document.getElementById("hideBtn").addEventListener("click", hide);
        document.getElementById("operInput").addEventListener("keydown", keydown);
    }
    function keydown(e){
        if (e.keyCode == 13){
            let li = document.getElementById("dialog").querySelector("li.list-li.active");
            if(li){
                li.click();
            }
        }else if(e.keyCode == 38){ //上
            let lis = document.getElementById("operList").querySelectorAll("li.list-li");
            let curr = document.getElementById("dialog").querySelector("li.list-li.active");
            if(curr){
                for(let i = 0; i < lis.length; i ++){
                    let li = lis[i];
                    if(li.classList.contains('active')){
                        li.classList.remove('active');
                        let idx = i - 1;
                        if(idx == -1){
                            idx = lis.length - 1;
                        }
                        curr = lis[idx];
                        curr.classList.add('active');
                        document.getElementById("operUl").scrollTo(0,curr.offsetTop - 400);
                        break;
                    }
                }
            }else{
               let li = document.getElementById("dialog").querySelector("li.list-li:last-child");
               li.classList.add('active');
            }
        }else if(e.keyCode == 40){ //下
            let lis = document.getElementById("operList").querySelectorAll("li.list-li");
            let curr = document.getElementById("dialog").querySelector("li.list-li.active");
            if(curr){
                for(let i = 0; i < lis.length; i ++){
                    let li = lis[i];
                    if(li.classList.contains('active')){
                        li.classList.remove('active');
                        let idx = i + 1;
                        if(idx == lis.length){
                            idx = 0;
                        }
                        curr = lis[idx];
                        curr.classList.add('active');
                        document.getElementById("operUl").scrollTo(0,curr.offsetTop - 400);
                        break;
                    }
                }
            }else{
               let li = document.getElementById("dialog").querySelector("li.list-li:first-child");
               li.classList.add('active');
            }
        }
    }
    function show(){
        document.getElementById("showBtn").style.display = "none";
        document.getElementById("hideBtn").style.display = "inline-block";
        let v = -840;
        var inter2 = setInterval(() => {
            v = v + 15;
            if(v >= 0){
                clearInterval(inter2);
                document.getElementById("operInput").focus();
                dialogShow = true;
            }
            document.getElementById("dialog").style.right = `${v}px`;
        }, 5);
    }
    function hide(){
        document.getElementById("showBtn").style.display = "inline-block";
        document.getElementById("hideBtn").style.display = "none";
        let v = 0;
        var inter2 = setInterval(() => {
            v = v - 15;
            if(v <= -825){
                clearInterval(inter2);
                document.getElementById("dialog").style.right = "-820px";
                dialogShow = false;
                listClean();
            }else{
                document.getElementById("dialog").style.right = `${v}px`;
            }
        }, 5);
    }
    function listClean(e){
        let li = document.getElementById("dialog").querySelector("li.list-li:first-child");
        if(li){
            let id = li.dataset.operationId;
            if(id == 0){
                return;
            }
        }
        setTimeout(() => {
            clearTimeout(timer);
            document.getElementById('operList').classList.add("hidden");
        }, 500)
    }
    function inputClean(e){
        clearTimeout(timer);
        document.getElementById('operDesc').innerHTML = '共找到0个接口';
        document.getElementById("operInput").value = "";
        document.getElementById('operList').classList.add("hidden");
    }
    function inputSearch(e){
        clearTimeout(timer);
        let val = e.target.value.trim();
        if (val === "") {
            inputClean();
        } else {
            timer = setTimeout(() => {
                postForm(`${serverUrl}/eurka/servive/url/find`, `uri=${val}`, function(data){
                    apiData = data;
                    renderLi(data);
                }, function(txt){
                    console.error(txt);
                });
            }, 300)
        }
    }
    function renderLi(items) {
        clearInterval(inter);
        let ul = document.getElementById("operUl");
        ul.innerHTML = "";
        if (items.length === 0) {
            let li = document.createElement("li");
            li.className = "list-li";
            li.setAttribute("data-operation-id", 0);
            let span1 = document.createElement("span");
            span1.className = "list-li-left";
            span1.innerText = "没有匹配到，若该接口是新接口，请点击此处进行接口数据同步";
            li.appendChild(span1);
            let span2 = document.createElement("span");
            span2.className = "list-li-right";
            li.appendChild(span2);
            ul.appendChild(li);
            liEvent(li);
            document.getElementById('operDesc').innerHTML = '共找到0个接口';
        } else {
            document.getElementById('operDesc').innerHTML = `共找到${items.length}个接口`;
            let idx = 0;
            inter = setInterval(() => {
                var item = items[idx];
                let li = document.createElement("li");
                li.setAttribute("className", "list-li");
                if(idx == 0){
                  li.className = "list-li active";
                }else{
                  li.className = "list-li";
                }
                li.setAttribute("data-operation-id", item.operationIdOriginal);
                li.setAttribute("data-tag", item.tagName);
                li.setAttribute("data-host", item.host);
                li.setAttribute("data-ng", item.newGateway);
                let btnCode = document.createElement("button");
                btnCode.className = "oper-kai createCode";
                btnCode.innerText = '代码';
                btnCode.title = '点击，复制代码';
                let btnCode2 = document.createElement("button");
                btnCode2.className = "oper-kai createCode";
                btnCode2.innerText = '地址';
                btnCode2.title = '点击，复制地址';
                let span1 = document.createElement("span");
                span1.className = "list-li-left";
                span1.appendChild(btnCode);
                span1.appendChild(btnCode2);
                let spanText = document.createElement("span");
                spanText.innerText = `[${item.serviceName}] [${item.httpMethod}] ${item.uri}`;
                span1.appendChild(spanText);
                li.appendChild(span1);
                let span2 = document.createElement("span");
                span2.className = "list-li-right";
                span2.innerText = item.desc;
                li.appendChild(span2);
                ul.appendChild(li);
                btnEvent(btnCode);
                btn2Event(btnCode2);
                liEvent(li);
                idx += 1;
                if(idx == items.length){
                    clearInterval(inter);
                }
            }, 30);
        }
        document.getElementById('operList').classList.remove("hidden");
    }

    function toast(msg){
        let commonStyle = `.toast{z-index: 100001;position:fixed;display:inline-block;right:700px;top:45px;font-size:14px;background: rgba(0,0,0,0.6);border-left: 0px;cursor:default;border-radius: 8px;padding: 5px 10px;color: #FFF;}`;
        let styleTextNode = document.createTextNode(commonStyle);
        let styleElement = document.createElement('style');
        styleElement.appendChild(styleTextNode)
        document.body.appendChild(styleElement);
        let rootDiv = document.createElement('div');
        rootDiv.setAttribute("id", "toast");
        document.body.appendChild(rootDiv);
        let rootHtml = `<div class="toast">${msg}</div>`;
        rootDiv.innerHTML = rootHtml;
        setTimeout(() => {
            document.getElementById('toast').remove()
        }, 2000);
    }

    function getScrollTop(){
        var scrollTop=0;
        if(document.documentElement&&document.documentElement.scrollTop){
            scrollTop=document.documentElement.scrollTop;
        }else if(document.body){
            scrollTop=document.body.scrollTop;
        }
        return scrollTop;
    }

    function copyText(text) {
        let box = document.createElement('div');
        box.setAttribute("id", "NewsToolBox");
        document.body.appendChild(box);
        let top = getScrollTop();
        var textarea = document.createElement("textarea");
        var currentFocus = document.activeElement;
        var toolBoxwrap = document.getElementById('NewsToolBox');
        toolBoxwrap.appendChild(textarea);
        textarea.value = text;
        textarea.focus();
        if (textarea.setSelectionRange) {
            textarea.setSelectionRange(0, textarea.value.length);
        } else {
            textarea.select();
        }
        var f = false;
        try {
            f = document.execCommand("copy");
        } catch (eo) {
        }
        toolBoxwrap.removeChild(textarea);
        currentFocus.focus();
        window.scrollTo(0,top);
        return f;
    }

    function btn2Event(element){
        element.addEventListener('click', function (e) {
            let id = e.currentTarget.parentNode.parentNode.dataset.operationId;
            let temp = apiData.filter(it => it.operationIdOriginal == id);
            if(temp.length > 0){
                let f = copyText(`${temp[0].uri}`);
                if(f){
                    toast("复制成功")
                }
            }else{
                toast("该接口没有返回值")
            }
            e.stopPropagation();
        });
    }
    function btnEvent(element){
        element.addEventListener('click', function (e) {
            let id = e.currentTarget.parentNode.parentNode.dataset.operationId;
            let temp = apiData.filter(it => it.operationIdOriginal == id);
            if(temp.length > 0){
                let items = temp[0].responseFields;
                let json = items.map(item => {
                    if(item.desc){
                        let it = {"title": `${item.desc}`, "dataIndex": `${item.name}`, "width": 100};
                        switch (item.type){
                            case 'Date':
                            case 'LocalDate':
                            case 'LocalDateTime':
                                it.scope = {"type": "Date", "props": { "formatStr": "YYYY-MM-DD HH:mm:ss" }};
                                break;
                            default:
                        };
                        return JSON.stringify(it, null, 2);
                    }else{
                        return null;
                    }
                }).filter(i => i).join(",\r\n");
                let f = copyText(`[${json}]`);
                if(f){
                    toast("复制成功")
                }
            }else{
                toast("该接口没有返回值")
            }
            e.stopPropagation();
        });
    }
    function liEvent(element){
        element.addEventListener('mouseenter', function (e) {
            this.classList.add('active')
            let id = e.currentTarget.dataset.operationId;
            let temp = apiData.filter(it => it.operationIdOriginal == id);
            let ti = document.getElementById("minetitle");
            if(null == ti){
                ti = document.createElement("div");
            }
            if(temp.length > 0){
                let item = temp[0];
                ti.innerHTML = `<div><b>服务</b>：${item.serviceName}</div><div><b>方式</b>：${item.httpMethod}</div><div><b>路径</b>：${item.uri}</div><div class="xk"><b>简介</b>：${item.desc}</div><div class="xk"><b>说明</b>：${item.description ? item.description : "无"}</div>`;
            }else if(id == 0){
                return false;
            }
            ti.setAttribute("id", "minetitle");
            ti.style.left=(e.pageX + 10) + "px";
            ti.style.top=(e.pageY) + "px";
            document.body.appendChild(ti);
        });
        element.addEventListener('mouseleave', function (e) {
            this.classList.remove('active');
            let ti = document.getElementById("minetitle");
            if(ti){
                document.body.removeChild(ti);
            }
        });
        element.addEventListener('mousemove', function (e) {
            let ti = document.getElementById("minetitle");
            if(e.target.nodeName == 'BUTTON'){
                if(ti){
                    ti.style.display = "none";
                }
            }else{
                ti.style.display = "inline-block";
            }
            if(ti){
                ti.style.left=(e.pageX + 10) + "px";
                ti.style.top=(e.pageY) + "px";
            }
        });
        element.addEventListener('click', function (e) {
            let id = e.currentTarget.dataset.operationId;
            if(id == 0){
                let rig = e.currentTarget.childNodes[1];
                if(rig.childNodes[0] && rig.childNodes[0].tagName == "SPAN" && ! sync){
                    rig.innerHTML = `<span style='color:red'>同步中, 请稍后...(${times++})</span>`;
                }else if(! sync){
                    rig.innerHTML = "<span style='color:red'>同步中...</span>";
                    postForm(`${serverUrl}/eurka/service/url/init`, null, function(data){
                        rig.innerHTML = "<span style='color:red'>同步完成，继续去查询吧，祝工作顺利。</span>";
                        times = 2;
                        sync = true;
                    }, function(msg){
                        rig.innerHTML = `<span style='color:red'>同步出现错误：${msg}</span>`;
                        times = 2;
                    });
                }else if(sync){
                    rig.innerHTML = "<span style='color:red'>已同步完成，请不要反复同步</span>";
                }
                return false;
            }
            let tag = e.currentTarget.dataset.tag;
            let host = e.currentTarget.dataset.host;
            let ng = e.currentTarget.dataset.ng;
            if(ng=='true'){
                window.open(`${host}/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config#/${tag}/${id}`);
            }else{
                window.open(`${host}swagger-ui.html#/${tag}/${id}`);
            }
            document.getElementById('operList').classList.add("hidden");
        });
    }
    initSearchUI();
    function documentKeyUp(e) {
        //ctrl + shift + q
        if(e.ctrlKey & e.shiftKey && e.keyCode==81){
            if(dialogShow){
                hide();
            }else{
                show();
            }
        }
        //ctrl + shift + f
        if(e.ctrlKey & e.shiftKey && e.keyCode==70){
            if(dialogShow){
                document.getElementById("operInput").focus();
            }else{
                show();
            }
        }
        //ctrl + shift + v
        if(e.ctrlKey & e.shiftKey && e.keyCode==86){
            inputClean();
            document.getElementById("operInput").focus();
        }
    }
    document.addEventListener('keyup', documentKeyUp, false);
})();